
/*******************************************************************************
 * Copyright (c) 2007 Jules White. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors: Jules White - initial API and implementation
 ******************************************************************************/
package org.refresh.prolog;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.refresh.core.intelligence.ObjectType;
import org.refresh.core.intelligence.ObjectView;

import com.sun.xml.internal.bind.v2.runtime.property.Property;

public class KnowledgeBase {
	
	private ObjectManager objectManager_;
	private AssertionManager assertionManager_;
	private List<FactProcessor> factPreProcessors_ = new LinkedList<FactProcessor>();
	private FactProducer factProducer_;
	private Map<Object,List<Fact>> facts_ = new HashMap<Object,List<Fact>>();
	private List<Fact> allFacts_ = new ArrayList<Fact>();
	
	public KnowledgeBase(AssertionManager mgr, ObjectManager omgr){
		factProducer_ = new BasicFactProducer(omgr);
		assertionManager_ = mgr;
		objectManager_ = omgr;
	}
	
	public KnowledgeBase(FactProducer fp, AssertionManager mgr, ObjectManager omgr){
		this(mgr,omgr);
		factProducer_ = fp;
	}

	public void add(Object obj, List<ObjectType> types, ObjectView view, List kb) {
		
		String id = objectManager_.addObject(obj);
		List<Fact> facts = facts_.get(id);
		if(facts == null){
			facts = factProducer_.produceFacts(obj, view.getView(obj),types, kb);
			
			LinkedList<Fact> pfacts = new LinkedList<Fact>();
			
			for(Fact pf : facts){
				for(FactProcessor fp : factPreProcessors_)
					pf = fp.process(pf);
				
				pfacts.add(pf);
			}
			
			facts_.put(id, pfacts);
			
			for(Fact f : pfacts){
				assertFact(f);
				allFacts_.add(f);
			}
		}
	}
	
	public void retractAll(){
		for(Fact pf : allFacts_){
			retractFact(pf);
		}
		allFacts_.clear();
	}
	

	public void remove(Object obj) {
		String id = objectManager_.getId(obj);
		List<Fact> facts = facts_.get(id);
		if(facts != null){
			for(Fact f : facts){
				retractFact(f);
				allFacts_.remove(f);
			}
			facts_.remove(id);
			
		}
	}
	
	public String snapshot(){
		String kb = "";
		for(Fact f : allFacts_){
			kb += assertionManager_.constructQuery(f)+".\n";
		}
		return kb;
	}
	
	
	public AssertionManager getAssertionManager() {
		return assertionManager_;
	}

	public void setAssertionManager(AssertionManager assertionManager) {
		assertionManager_ = assertionManager;
	}

	public void assertFact(Fact f){
		assertionManager_.assertFact(f);
	}
	
	public void retractFact(Fact f){
		assertionManager_.retractFact(f);
	}

	public List<FactProcessor> getFactPreProcessors() {
		return factPreProcessors_;
	}

	public void setFactPreProcessors(List<FactProcessor> factPreProcessors) {
		factPreProcessors_ = factPreProcessors;
	}

	public FactProducer getFactProducer() {
		return factProducer_;
	}

	public void setFactProducer(FactProducer factProducer) {
		factProducer_ = factProducer;
	}

}
